Clover icon

compiler

  1. Project Clover database Mon Jan 2 2023 15:09:37 MST
  2. Package com.google.javascript.jscomp

File ControlFlowGraph.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

4
35
9
3
206
83
23
0.66
3.89
3
2.56

Classes

Class Line # Actions
ControlFlowGraph 32 31 20 4
0.990%
ControlFlowGraph.Branch 109 1 1 0
1.0100%
ControlFlowGraph.AbstractCfgNodeTraversalCallback 143 3 2 0
1.0100%
 

Contributing tests

This file is covered by 7723 tests. .

Source view

1    /*
2    * Copyright 2008 The Closure Compiler Authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16   
17    package com.google.javascript.jscomp;
18   
19    import com.google.javascript.jscomp.NodeTraversal.Callback;
20    import com.google.javascript.jscomp.graph.LinkedDirectedGraph;
21    import com.google.javascript.rhino.Node;
22    import com.google.javascript.rhino.Token;
23   
24    import java.util.Comparator;
25   
26    /**
27    * Control flow graph.
28    *
29    *
30    * @param <N> The instruction type of the control flow graph.
31    */
 
32    class ControlFlowGraph<N> extends
33    LinkedDirectedGraph<N, ControlFlowGraph.Branch> {
34   
35    /**
36    * A special node marked by the node value key null to a singleton
37    * "return" when control is transferred outside of the current control flow
38    * graph.
39    */
40    private final DiGraphNode<N, ControlFlowGraph.Branch> implicitReturn;
41   
42    private final DiGraphNode<N, ControlFlowGraph.Branch> entry;
43   
44    /**
45    * Constructor.
46    */
 
47  76417 toggle ControlFlowGraph(
48    N entry, boolean nodeAnnotations, boolean edgeAnnotations) {
49  76417 super(nodeAnnotations, edgeAnnotations);
50  76417 implicitReturn = createDirectedGraphNode(null);
51  76417 this.entry = createDirectedGraphNode(entry);
52    }
53   
54    /**
55    * Gets the implicit return node.
56    *
57    * @return Return node.
58    */
 
59  735161 toggle public DiGraphNode<N, ControlFlowGraph.Branch> getImplicitReturn() {
60  735161 return implicitReturn;
61    }
62   
63    /**
64    * Gets the entry point of the control flow graph. In general, this should be
65    * the beginning of the global script or beginning of a function.
66    *
67    * @return The entry point.
68    */
 
69  485688 toggle public DiGraphNode<N, ControlFlowGraph.Branch> getEntry() {
70  485688 return entry;
71    }
72   
73    /**
74    * Checks whether node is the implicit return.
75    *
76    * @param node Node.
77    * @return True if the node is the implicit return.
78    */
 
79  6461 toggle public boolean isImplicitReturn(
80    DiGraphNode<N, ControlFlowGraph.Branch> node) {
81  6461 return node == implicitReturn;
82    }
83   
84    /**
85    * Connects the node to the explicit return.
86    *
87    * @param srcValue Node.
88    * @param edgeValue Edge.
89    */
 
90  0 toggle public void connectToImplicitReturn(N srcValue, Branch edgeValue) {
91  0 super.connect(srcValue, edgeValue, null);
92    }
93   
94    /**
95    * Gets a comparator for the nodes. The default implementation returns
96    * {@code null}. See {@link ControlFlowGraph#getOptionalNodeComparator}.
97    * @param isForward Whether the comparator sorts the nodes in the direction of
98    * the flow.
99    * @return a comparator or null (in particular, if not overridden)
100    */
 
101  9 toggle public Comparator<DiGraphNode<N, Branch>> getOptionalNodeComparator(
102    boolean isForward) {
103  9 return null;
104    }
105   
106    /**
107    * The edge object for the control flow graph.
108    */
 
109    public static enum Branch {
110    /** Edge is taken if the condition is true. */
111    ON_TRUE,
112    /** Edge is taken if the condition is false. */
113    ON_FALSE,
114    /** Unconditional branch. */
115    UNCOND,
116    /**
117    * Exception-handling code paths.
118    * Conflates two kind of control flow passing:
119    * - An exception is thrown, and falls into a catch or finally block
120    * - During exception handling, a finally block finishes and control
121    * passes to the next finally block.
122    * In theory, we need 2 different edge types. In practice, we
123    * can just treat them as "the edges we can't really optimize".
124    */
125    ON_EX,
126    /** Possible folded-away template */
127    SYN_BLOCK;
128   
 
129  8091 toggle public boolean isConditional() {
130  8091 return this == ON_TRUE || this == ON_FALSE;
131    }
132    }
133   
134    /**
135    * Abstract callback to visit a control flow graph node without going into
136    * subtrees of the node that are also represented by other
137    * control flow graph nodes.
138    *
139    * <p>For example, traversing an IF node as root will visit the two subtrees
140    * pointed by the {@link ControlFlowGraph.Branch#ON_TRUE} and
141    * {@link ControlFlowGraph.Branch#ON_FALSE} edges.
142    */
 
143    public abstract static class AbstractCfgNodeTraversalCallback implements
144    Callback {
 
145  44514 toggle @Override
146    public final boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
147    Node parent) {
148  44514 if (parent == null) {
149  16074 return true;
150    }
151  28440 return !isEnteringNewCfgNode(n);
152    }
153    }
154   
155    /**
156    * @return True if n should be represented by a new CFG node in the control
157    * flow graph.
158    */
 
159  131605 toggle public static boolean isEnteringNewCfgNode(Node n) {
160  131605 Node parent = n.getParent();
161  131605 switch (parent.getType()) {
162  7108 case Token.BLOCK:
163  0 case Token.SCRIPT:
164  255 case Token.TRY:
165  7363 return true;
166  2253 case Token.FUNCTION:
167    // A function node represents the start of a function where the name
168    // bleeds into the local scope and parameters are assigned
169    // to the formal argument names. The node includes the name of the
170    // function and the LP list since we assume the whole set up process
171    // is atomic without change in control flow. The next change of
172    // control is going into the function's body, represented by the second
173    // child.
174  2253 return n != parent.getFirstChild().getNext();
175  12 case Token.WHILE:
176  18 case Token.DO:
177  304 case Token.IF:
178    // These control structures are represented by a node that holds the
179    // condition. Each of them is a branch node based on its condition.
180  334 return NodeUtil.getConditionExpression(parent) != n;
181   
182  624 case Token.FOR:
183    // The FOR(;;) node differs from other control structures in that
184    // it has an initialization and an increment statement. Those
185    // two statements have corresponding CFG nodes to represent them.
186    // The FOR node only represents the condition check for each iteration.
187    // That way the following:
188    // for(var x = 0; x < 10; x++) { } has a graph that is isomorphic to
189    // var x = 0; while(x<10) { x++; }
190  624 if (NodeUtil.isForIn(parent)) {
191    // TODO(user): Investigate how we should handle the case where
192    // we have a very complex expression inside the FOR-IN header.
193  108 return n != parent.getFirstChild();
194    } else {
195  516 return NodeUtil.getConditionExpression(parent) != n;
196    }
197  26 case Token.SWITCH:
198  30 case Token.CASE:
199  216 case Token.CATCH:
200  0 case Token.WITH:
201  272 return n != parent.getFirstChild();
202  120759 default:
203  120759 return false;
204    }
205    }
206    }